home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / patches / csfix.lha / csfix / Source / csfix.c next >
C/C++ Source or Header  |  1995-01-03  |  8KB  |  267 lines

  1. /* csfix.c    (c) Frank Meijer, 1995.
  2.  |
  3.  | PURPOSE:
  4.  |   Allow ComicSetter to run under OS 3.0.
  5.  |
  6.  | HISTORY:
  7.  |   950103: Completed version 1.0.
  8.  |   950101: Works fine.  To be done: install/remove,
  9.  |           workbench launch and get rid of debugging.
  10.  |   941231: Fix bug in mem.asm (saving register A6).
  11.  |   941229: Identify by screen title, not by task name.
  12.  |   941226: Intercept calls to AllocMem() and FreeMem().
  13.  |
  14.  | SYMPTOM:
  15.  |   The CS display would get scrambled on a SAVE (not always,
  16.  |   but almost).  After that, quitting from CS would cause a guru.
  17.  |
  18.  | DIAGNOSIS:
  19.  |   Before a SAVE, CS reduces the screen depth to 1 plane.
  20.  |   It restores the depth to 4 after the save is done.
  21.  |   However, the backdrop window's BitMap does not get updated,
  22.  |   so that if the plane memory allocated for planes 1..3 is not
  23.  |   the same as before the SAVE, the window is out of sync with
  24.  |   the screen.
  25.  |   I assume this worked in OS 1.3 because there were no other
  26.  |   allocations done during the SAVE, so that the memory was
  27.  |   always allocated at the same location.  However, under OS 3.0
  28.  |   some memory is allocated during the SAVE.
  29.  |
  30.  | SOLUTION:
  31.  |   Intercept the calls to FreeMem() and AllocMem().
  32.  |   When CS frees the plane memory, don't really free it but
  33.  |   store the addresses.  When CS re-allocates plane memory,
  34.  |   don't allocate it but return the old pointers.
  35.  |   Note that this should not be done when all planes are freed,
  36.  |   but only when planes 1..3 are freed.
  37.  |
  38.  | NOTES:
  39.  | - In order to verify that the request comes from CS, we don't
  40.  |   check the task name but the active screen title.  This has the
  41.  |   advantage that changes from interlace to non-interlace are
  42.  |   not even seen because the CS screen is closed at that time.
  43.  |   Also, the screen title is independent from the program name
  44.  |   so if the user renamed CS to someting else, it still works.
  45.  |   This algorithm will fail if SAVE causes chunks of the
  46.  |   same size as the screen planes to be allocated, but that does
  47.  |   never seem to be the case.
  48.  | - Plane memory is either 16000 or 32000 bytes per plane.
  49.  |   For non-interlaced: 640*200/8 = 16000.  Double for interlaced.
  50.  |
  51.  */
  52.  
  53. #include <exec/types.h>
  54. #include <exec/execbase.h>
  55. #include <exec/tasks.h>
  56. #include <exec/memory.h>
  57. #include <exec/ports.h>
  58. #include <intuition/intuition.h>
  59. #include <intuition/intuitionbase.h>
  60. #include "defs.h"
  61. #include "mem.h"
  62. #include "info.h"
  63.  
  64. #define AllocMem_LIBOFF -198
  65. #define FreeMem_LIBOFF  -210
  66.  
  67. struct ExecBase *ExecBase = NULL;
  68. struct IntuitionBase *IntuitionBase = NULL;
  69.  
  70. static APTR CSbuf[3] = { NULL, NULL, NULL };
  71. static LONG CSsize = 0;        /* plane memory size */
  72. static int  CSplane = 0;       /* last freed plane + 1 */
  73. static BOOL CSfreeall = FALSE; /* true if plane 0 is also being freed */
  74.  
  75. #define PROGNAME "CSfix v1.0"
  76. #define PORTNAME "CSfix msgport"
  77. #define INFO_DURATION 2 /* info window display time, in seconds */
  78.  
  79. static struct MsgPort *msgport;
  80.  
  81. /*----------------------------------------------------------------*/
  82. __geta4 APTR myAllocMem( LONG size, LONG type )
  83. {
  84.    APTR   memaddr=NULL;   /* return value */
  85.    struct Screen *screen;
  86.  
  87.    if ( (CSplane > 0) && (size == CSsize) ) {
  88.       screen = IntuitionBase->ActiveScreen;
  89.       if ( screen && screen->Title &&
  90.            (memcmp(screen->Title, "ComicSetter", 11) == 0) ) {
  91.          if (CSplane == 3) {
  92.             /* this is the first allocation */
  93.             memaddr = CSbuf[0];
  94.             CSplane = 1;
  95.          } else {
  96.             /* not the first but plane memory has been saved */
  97.             memaddr = CSbuf[CSplane];
  98.             CSplane++;
  99.             if (CSplane == 3)
  100.                CSplane = 0;  /* done */
  101.          }
  102. #ifdef DEBUG
  103.          printf( "AllocMem( size=%ld, type=%08lx ) -> %08lx\n", size, type, memaddr );
  104. #endif
  105.       }
  106.    }
  107.  
  108.    if (memaddr == NULL)
  109.       memaddr = CALLrealAllocMem( size, type );
  110.  
  111.    return( memaddr );
  112. }
  113.  
  114. /*----------------------------------------------------------------*/
  115. __geta4 void myFreeMem( APTR memaddr, LONG size )
  116. {
  117.    BOOL really_free = TRUE;
  118.    struct Screen *screen;
  119.    struct BitMap *bitmap;
  120.  
  121.    if ((size == 16000) || (size == 32000)) {
  122.  
  123.       /* When changing between interlaced and non-interlaced, */
  124.       /* the active screen is the Workbench.  We can ignore   */
  125.       /* those cases because CS handles them correctly.       */
  126.       /* The only case that concern is is the temporary plane */
  127.       /* de-allocation/allocation that is done during SAVE.   */
  128.  
  129.       screen = IntuitionBase->ActiveScreen;
  130.       if ( screen && screen->Title &&
  131.            (memcmp(screen->Title, "ComicSetter", 11) == 0) ) {
  132.          bitmap = &(screen->BitMap);
  133.          if (memaddr == bitmap->Planes[0])
  134.             CSfreeall = TRUE;
  135.          else {
  136.             if ( (NOT CSfreeall) && (memaddr == bitmap->Planes[CSplane+1]) ) {
  137. #ifdef DEBUG
  138.                printf( "FreeMem( memaddr=%08lx size=%ld ) --> CSbuf[%d]\n",
  139.                        memaddr, size, CSplane );
  140. #endif
  141.                CSbuf[CSplane] = memaddr;
  142.                CSplane++;
  143.                CSsize = size;
  144.                really_free = FALSE;
  145.             }
  146.             CSfreeall = FALSE;
  147.          }
  148.       }
  149.  
  150.    }
  151.  
  152.    if (really_free)
  153.       CALLrealFreeMem( memaddr, size );
  154.  
  155.    return;
  156. }
  157.  
  158. /*----------------------------------------------------------------*/
  159. main( int argc, char *argv[] )
  160. {
  161.    enum { doInstall, doToggle, doQuit } action;
  162.    struct Message *msg;
  163.  
  164.    /* Open libraries */
  165.    ExecBase = (struct ExecBase *) OpenLibrary( "exec.library", 0 );
  166.    if (ExecBase == NULL) goto End;
  167.    IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 0);
  168.    if (IntuitionBase == NULL) goto End;
  169.  
  170.    /* Get requested action from command line parameter */
  171.    action = doToggle;
  172.    if (argc > 1) {
  173.       if (STREQ( argv[1], "install" ))
  174.          action = doInstall;
  175.       else if (STREQ( argv[1], "quit" ))
  176.          action = doQuit;
  177.       else {
  178.          info_show( NULL, FALSE, PROGNAME, "invoked with invalid option!", INFO_DURATION );
  179.          goto End;
  180.       }
  181.    }
  182.  
  183.    /* See if there's already a copy of me running */
  184.    msgport = (struct MsgPort *) FindPort( PORTNAME );
  185.  
  186.    /* If we should toggle, determine which way */
  187.    if (action == doToggle)
  188.       if (msgport == NULL)
  189.          action = doInstall;
  190.       else
  191.          action = doQuit;
  192.  
  193.    /* Perform the requested action */
  194.    if (action == doQuit) {
  195.  
  196.       /* quit: send a message to the port of the copy of myself */
  197.       if (msgport != NULL) {
  198.          msg = (struct Message *) AllocMem( sizeof(*msg), MEMF_PUBLIC );
  199.          if (msg == NULL) goto End;
  200.          msg->mn_Node.ln_Type = NT_MESSAGE;
  201.          PutMsg( msgport, msg );
  202.       }
  203.  
  204.    }
  205.    else { /* doInstall */
  206.  
  207.       /* Cannot install twice */
  208.       if (msgport != NULL) {
  209.          info_show( NULL, FALSE, PROGNAME, "is already installed!", INFO_DURATION );
  210.          goto End;
  211.       }
  212.  
  213.       /* Create the message port */
  214.       msgport = (struct Msgport *) CreatePort( PORTNAME, 0 );
  215.       if (msgport == NULL) goto End;
  216.  
  217.       /* Intercept calls to AllocMem */
  218.       realAllocMem = (void *) SetFunction( ExecBase, AllocMem_LIBOFF, CALLmyAllocMem );
  219.       if (realAllocMem == NULL) goto End;
  220.  
  221.       /* Intercept calls to FreeMem */
  222.       realFreeMem = (void *) SetFunction( ExecBase, FreeMem_LIBOFF, CALLmyFreeMem );
  223.       if (realFreeMem == NULL) goto End;
  224.  
  225.       /* Tell the user */
  226.       info_show( NULL, FALSE, PROGNAME, "has been installed", INFO_DURATION );
  227.  
  228.       /* Wait for a message */
  229.       WaitPort( msgport );
  230.  
  231.       /* Delete the message */
  232.       while( msg = (struct Message *)GetMsg(msgport) )
  233.          FreeMem( msg, sizeof(msg) );
  234.  
  235.       /* Delete the message port */
  236.       DeletePort( msgport );
  237.  
  238.       /* Tell the user */
  239.       info_show( NULL, FALSE, PROGNAME, "has been removed", INFO_DURATION );
  240.  
  241.    }
  242.  
  243. End:
  244.    /* Restore original vectors */
  245.    if (realAllocMem != NULL)
  246.       SetFunction( ExecBase, AllocMem_LIBOFF, realAllocMem );
  247.    if (realFreeMem != NULL)
  248.       SetFunction( ExecBase, FreeMem_LIBOFF, realFreeMem );
  249.  
  250.    /* Close the libraries */
  251.    if (ExecBase != NULL)
  252.       CloseLibrary( ExecBase );
  253.    if (IntuitionBase != NULL)
  254.       CloseLibrary( IntuitionBase );
  255.  
  256.    return( 0 );
  257. }
  258.  
  259. /*----------------------------------------------------------------*/
  260. int wbmain()  /* When invoked from Workbench */
  261. {
  262.  
  263.    /* Call the main program as if we were launched from CLI */
  264.    main( 0, NULL );
  265.  
  266.    return( 0 );
  267. }